/***************************************************************************
 创建者: 华磊
 开始时间: 2020.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2020.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "mathauthorityallowance.h"
#include "getsysinfo.h"

MathAuthorityAllowance::MathAuthorityAllowance(QString fileNameIn,QString licenseFileNameIn)
{
    fileName=fileNameIn;
    licenseFileName = licenseFileNameIn;
    currentBootCount=-1;

}

int MathAuthorityAllowance::getLicenseDayLefted()
{
    if(ENUM_TIME_NORMAL==registerType || ENUM_TIME_GOING_PASSED==registerType )
    {
        return checkDate(lockMachineStr);
    }
    return -1000;

}

int MathAuthorityAllowance::loginIn(UserInfo userInfo)
{
    //文件不存在时，可以登录
    if(registerType == ENUM_REGISTER_FILE_NO_EXIST
            ||ENUM_REGISTER_FILE_NODE_ERROR==registerType
            ||ENUM_REGISTER_FILE_CHECK_CODE_ERROR==registerType)
    {
        return 0;
    }

    if(ENUM_POWER_ADMIN == userInfo.account)
    {
        //adminPwd.toStdString().length()>0 &&
        if( userInfo.password == adminPwd.toStdString())
        {
            return 1;//登录成功
        }
        else
        {
            return -1;//登录失败
        }
    }
    else if(ENUM_POWER_COMMON_CONSUMER == userInfo.account)
    {
        if(userInfo.password == userPwd.toStdString())
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }

    return -1;
}

int MathAuthorityAllowance::refreshAuthorityStatus()
{
    int returnKey=readUserInfo(fileName);
    if(E_READ_USER_INFO_ERROR_NO_FILE==returnKey)
    {
        registerType=ENUM_REGISTER_FILE_NO_EXIST;
        return registerType;
    }
    else if(E_READ_USER_INFO_ERROR_NO_NODE_USER==returnKey||
            E_READ_USER_INFO_ERROR_NO_NODE_ADMIN==returnKey||
            E_READ_USER_INFO_ERROR_NO_NODE_POLLCODE==returnKey||
            E_READ_USER_INFO_ERROR_NO_NODE_BOOT_COUNT==returnKey)
    {
        registerType=ENUM_REGISTER_FILE_NODE_ERROR;
        return registerType;
    }
    /**************************************************************
     * 日期：2018年10月26日
     * 修改人：丁培
     * 修改内容:添加注册码读取函数，分离注册码与User文件　readLicenseInfo
     * ************************************************************/
    returnKey = readLicenseInfo(licenseFileName);
    if(E_READ_USER_INFO_ERROR_NO_FILE==returnKey)
    {
        registerType=ENUM_REGISTER_FILE_NO_EXIST;
        return registerType;
    }
    else if(E_READ_USER_INFO_ERROR_NO_NODE_POLLCODE==returnKey)
    {
        registerType=ENUM_REGISTER_FILE_NODE_ERROR;
        return registerType;
    }


    serialNumber= getStandardNum();

    registerType = decrypt(pollCodeStr);

#ifdef D_USE_BOOT_COUNT_CHECK
    if(currentBootCount>BOOT_COUNT_LIMIT || currentBootCount<-1)
    {
        registerType = ENUM_BOOT_COUNT_EXCEED;
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,currentBootCount>BOOT_COUNT_LIMIT || currentBootCount<-1";

    }
#endif
    return registerType;
}

int MathAuthorityAllowance::getAuthorityStatus()
{
//    return ENUM_TIME_NORMAL;//hualei todo
    return registerType;
}


QString MathAuthorityAllowance::getLockTime()
{
    return lockMachineStr;
}

QString MathAuthorityAllowance::getRegisterNumber()
{
    return pollCodeStr;
}

QString MathAuthorityAllowance::getHardDiskSerialNumber()
{
    return serialNumber;
}

void MathAuthorityAllowance::saveRegFile(QString xmlFile)
{
    openXml(xmlFile);
    writeXml("licenseCode",pollCodeStr);
    closeWriteXml(xmlFile);

}

int MathAuthorityAllowance::readUserInfo(QString xmlFile)
{

    if(!openXml(xmlFile))
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,openXml(xmlFile)";

        return E_READ_USER_INFO_ERROR_NO_FILE;
    }
    int readResult;
    readResult=readXml("User",userPwd);
    if(-1==readResult)
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,User";

        return E_READ_USER_INFO_ERROR_NO_NODE_USER;
    }
    readResult=readXml("Admin",adminPwd);
    if(-1==readResult)
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,Admin";

        return E_READ_USER_INFO_ERROR_NO_NODE_ADMIN;
    }
    readResult=readXml("serialCodeMethod",serialCodeMethod);
    if(-1==readResult)
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,serialCodeMethod";

        return E_READ_USER_INFO_ERROR_NO_NODE_SERIAL_METHOD;
    }
    readResult=readXml("BootCount",currentBootCount);
    if(-1==readResult)
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,BootCount";

        return E_READ_USER_INFO_ERROR_NO_NODE_BOOT_COUNT;
    }
    currentBootCount++;
    if(false==writeXml("BootCount",currentBootCount))
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,BootCount";

        return E_READ_USER_INFO_ERROR_NO_NODE_BOOT_COUNT;
    }
    closeWriteXml(xmlFile);


    return E_READ_USER_INFO_OK;
}
int MathAuthorityAllowance::readLicenseInfo(QString xmlFile)
{
    if(!openXml(xmlFile))
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,openXml(xmlFile)";

        return E_READ_USER_INFO_ERROR_NO_FILE;
    }
    int readResult;
    readResult=readXml("licenseCode",pollCodeStr);
    if(-1==readResult)
    {
        qDebug()<<"MathAuthorityAllowance::readUserInfo,error,pollCode";

        return E_READ_USER_INFO_ERROR_NO_NODE_POLLCODE;
    }
    closeWriteXml(xmlFile);


    return E_READ_USER_INFO_OK;
}

int MathAuthorityAllowance::setRegisterNumber(string registerString, ReturnRegisterStatus &returnStatus)
{
    int returnFlag = 1;

    pollCodeStr = QString::fromStdString(registerString);
    POLLCODE_STATUS_TYPE registerOk = decrypt(pollCodeStr);

    if(ENUM_TIME_NORMAL==registerOk || ENUM_TIME_GOING_PASSED==registerOk)
    {
        //保存注册码文件
        saveRegFile(licenseFileName);
    }

    refreshAuthorityStatus();

    returnStatus.returnStatus = registerType;
    returnStatus.returnLockTime = lockMachineStr.toStdString();
    returnStatus.returnRegisterNumber = registerString;

    returnFlag = 0;
    return returnFlag;
}

int MathAuthorityAllowance::changePasswd(UserInfo userInfo, int changeAccount,string oldPasswd, string newPasswd, int &returnFlag)
{
    if(ENUM_POWER_ADMIN == userInfo.account)
    {
        openXml(fileName);
        if(ENUM_POWER_ADMIN == changeAccount)
        {
            if(adminPwd.toStdString() == oldPasswd)
            {
                adminPwd = QString::fromStdString(newPasswd);
                writeXml("Admin",adminPwd);

                returnFlag = 1;
            }
            else
            {
                returnFlag = -1;
            }
        }
        else if(ENUM_POWER_COMMON_CONSUMER == changeAccount)
        {
            userPwd = QString::fromStdString(newPasswd);
            writeXml("User",userPwd);
            returnFlag = 1;
        }
         closeWriteXml(fileName);

    }
    else if(ENUM_POWER_COMMON_CONSUMER == userInfo.account)
    {
            returnFlag = -2;
    }

    return returnFlag;
}



POLLCODE_STATUS_TYPE MathAuthorityAllowance::decrypt(QString registerStr)
{
    QString strNum = getNum(registerStr);

    lockMachineStr = getDate(registerStr);

    qDebug() << "**strNum**"<<strNum<<"**strDate**"<<lockMachineStr<<endl;

    if(strNum == serialNumber)
    {
        int endDay = checkDate(lockMachineStr);
        if(endDay >= 0 )
        {
            if(endDay > 7)
            {

                return   ENUM_TIME_NORMAL;
            }
            else
            {
                //消息预留
                //注册码快要过期

                return ENUM_TIME_GOING_PASSED;
            }
        }
        else
        {
            //消息预留
            //注册码已经过期，请联系厂家进行注册

            return ENUM_TIME_PASSED;
        }
    }
    else
    {
        //消息预留
        //序列号不正确，请联系厂家进行注册

        return ENUM_SERIAL_UNEQUAL;
    }

}


QString MathAuthorityAllowance::getNum(QString s)
{
    MathModeDecryptBase objMathModeDecryptBase(MathModeDecryptBase::E_ProgramModeType_MAIN);
    return objMathModeDecryptBase.getNum(s);
}

QString MathAuthorityAllowance::getDate(QString in)
{
    MathModeDecryptBase objMathModeDecryptBase(MathModeDecryptBase::E_ProgramModeType_MAIN);
    return objMathModeDecryptBase.getDate(in);
}

int MathAuthorityAllowance::checkDate(QString text)
{
    qDebug() <<"**text**"<<__FUNCTION__<<"****"<<text<<endl;

    //加密序列号 解密后的日期
    int year = text.left(4).toInt();
    int month = text.mid(4,2).toInt();
    int day = text.mid(6,2).toInt();

    //当前日期
    QDate currentDate = QDate::currentDate();
    int currentyear = currentDate.year();
    int currentmonth = currentDate.month();
    int currentday = currentDate.day();

    QDate date1(year,month,day);
    QDate date2(currentyear,currentmonth,currentday);

//    qDebug() << "***date1***year**"<<year<<"*****month***"<<month<<
//                "**day***"<<day<<
//                "**date1***year**"<<date1.year() << "**month**"<<date1.month()<<
//                "***day**"<<date1.day()<<
//                "**current**year***"<<currentyear<<"**currentMonth***"<<currentmonth<<
//                "***currentDay**"<<currentday<<
//                "**date2**year**"<<date2.year()<<"**month***"<<date2.month()<<
//                "***day**"<<date2.day()<<endl;
    if(date1 < date2)
    {
        return -1;//过期
    }
    else//date1 >= date2 有效期 大于等于 现在日期
    {
        if(year == currentyear && month == currentmonth)//同年同月，日期相减
        {
            return day - currentday ;
        }
        else if(year == currentyear)//同年
        {
            int dayInYear = getDayInYear(year, month, day);
            int currentdayInYear = getDayInYear(currentyear, currentmonth, currentday);
            qDebug()<<dayInYear-currentdayInYear;
            return dayInYear-currentdayInYear ;
        }
        else //年份不同
        {
            int d1,d2,d3;
            d1 = getDayInYear(year,month,day);//有效期所在年份的第几天
            if(isLeep(currentyear))//当前日期所在当年，距离年终的剩余天数
                d2 = 366 - getDayInYear(currentyear,currentmonth,currentday);
            else
                d2 = 365 - getDayInYear(currentyear,currentmonth,currentday);

            d3 = 0;
            for(int  y = currentyear+1; y < year; y++)
            {
                if(isLeep(y))
                {
                    d3 = 366;//原 d3 == 366;??
                }
                else
                {
                    d3+= 365;
                }
            }
            qDebug()<<d1+d2+d3;
            return d1+d2+d3;
        }
    }
}

bool MathAuthorityAllowance::isLeep(int year)
{
    //return ((year % 4 == 0) || (year % 400 == 0) && (year % 100 != 0));
    return ((year % 4 == 0) || ((year % 400 == 0) && (year % 100 != 0)));
}

int MathAuthorityAllowance::getDayInYear(int year,int month,int day)
{
    int customDay[12] = {31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
    if(isLeep(year))
    {
        customDay[1] = 29;
    }
    for(int i = 0; i < month - 1;++i)
    {
        day += customDay[i];
    }

    return day;
}


QString MathAuthorityAllowance::getStandardNum()
{
    QString genuineNum = "";

#if 1
    char  serial[256]={0};
    int returnFlag;

    getAllMac();

    if(1==serialCodeMethod)
    {
        returnFlag=getdiskid( serial );
    }
    else if(2==serialCodeMethod)
    {
        returnFlag=getmacaddr_method2( serial,"enp1s0");
    }
    else if(3==serialCodeMethod)
    {
        returnFlag=getmacaddr_method2( serial,"eth0");
    }
    else if(4==serialCodeMethod)
    {
        returnFlag=getmacaddr_method2( serial,"eth1");
    }
    else if(5==serialCodeMethod)
    {
        returnFlag= getdiskid_method3(serial);
        //174604A002E5 异常
        //174604A01566 异常
        //173910803654 正常
//        returnFlag=0;
//        strcpy(serial, "174604A01566");
    }
    else if(8==serialCodeMethod)
    {
        returnFlag= getdiskid_method3(serial);

    }
    else if(6==serialCodeMethod)
    {
//        returnFlag= getdiskid_method4(serial);
//        returnFlag= get_cpuid(3,serial);
//        returnFlag= get_serial_by_diskname("mmcblk0",serial);
        //174604A002E5 异常
        //174604A01566 异常
        //173910803654 正常
//        returnFlag=0;
//        strcpy(serial, "174604A01566");
    }
    else if(7==serialCodeMethod)
    {
//        returnFlag= getmacaddr_method3( "enp1s0",serial);

    }
    else
    {
        qDebug()<<"error : serialCodeMethod is not right!serialCodeMethod:"<<serialCodeMethod;
        return 0;
    }

   if( 0==returnFlag)
   {

       if(1==serialCodeMethod)
       {
        genuineNum=QString(serial);//无法识别0 ‘\0'
       }
       else if(5==serialCodeMethod)
       {
           QString tmpString;
           for(int i=6;i<12;i++)//截取末尾６个字符。ｓandisk正常返回１２个字符。
           {
               tmpString.clear();
               genuineNum+=tmpString.sprintf("%d",(unsigned char)serial[i]);
           }
       }
       else if(8==serialCodeMethod)
       {
           //agarade正常返回20个字符。
//           genuineNum+=QChar(serial[8]);//年尾
//           genuineNum+=QChar(serial[9]);//年尾
//           genuineNum+=QChar(serial[10]);//月
//           genuineNum+=QChar(serial[11]);//月尾
//           genuineNum+=QChar(serial[12]);//日
//           genuineNum+=QChar(serial[13]);//日尾

           genuineNum+=QString(serial).right(12);//序列尾
           qDebug()<<"-----------------------------------right******genuineNum:"<<genuineNum;
       }
       else
       {
          QString tmpString;
          for(int i=0;i<6;i++)
          {
              tmpString.clear();
              genuineNum+=tmpString.sprintf("%d",(unsigned char)serial[i]);
          }
       }


       qDebug()<<"genuineNum="<<genuineNum;
#else
    //通过命令行获取信息
    //正则提取,结合给genuineNum
    QString serialNum("\\s*Serial\\s*Number:\\s*(\\w*)\\s*");//硬盘序列号
    //QRegExp rx1(cpuid);
    QRegExp rx2(serialNum);
    if(system("hdparm -I /dev/sda | grep Serial > tmpGenuine.txt")==0)
    {
        QFile *tmpFile = new QFile("tmpGenuine.txt");//临时存放文件
        if(tmpFile->open(QIODevice::ReadOnly|QIODevice::Text))
        {
            while(!tmpFile->atEnd())
            {
                QString tmpLine;
                tmpLine = tmpFile->readLine();
                tmpLine.indexOf(rx2);
                genuineNum += rx2.cap(1);
            }
            //qDebug()<<"genuineNum:"<<genuineNum;
        }
        tmpFile->close();

#endif
        QString standardNum;
        /**拆分个体**/
        while(genuineNum.size()<12)
        {
            genuineNum = "0" + genuineNum;//补足12位置
        }
        //英文转数字
        QByteArray ba2  = genuineNum.right(12).toLatin1();
        char *charDate = ba2.data();
        for(int i = 0; i < 12;i++)
        {
            //174604A002E5
            //174604A01566
            if(charDate[i]<='Z' && charDate[i]>='A')
            {
                int tmp = charDate[i]-'A';
                //qDebug()<<tmp;
                standardNum += QString::number( tmp );
            }
            else
            {
                standardNum += QString(charDate[i]);
            }
        }


        //多余裁剪
        QString tmpStr = standardNum.right(12);
        QString tmpRightStr=tmpStr.right(6);
        QString tmpLeftStr=tmpStr.left(6);
        standardNum=tmpRightStr+tmpLeftStr;
        qDebug()<<"**standardNum:"<<standardNum;
        return standardNum;
    }
    else
    {
        //消息预留
        //获取不到序列号
        qDebug()<<"can not get the Serial Num";
        return 0;
    }
}
